[GitHub] Dependabot security updatesのPull Requestが未CloseならCI/CDをFailさせる
こんにちは、CX事業本部 IoT事業部の若槻です。
前回は、Dependabot security updatesがOpenしたPull Requestを自動でMergeする方法を確認しました。
しかし、修正をMergeは自動で行いたくないが、脆弱性を含んだコードを本番環境やステージング環境へリリースはさせたくないので、未CloseならCI/CDをFailさせたい、という場合もあるかと思います。
今回は、GitHubでDependabot security updatesのPull Requestが未Close(Open中)ならCI/CDをFailさせる方法を確認してみました。
やってみる
RepositoryのPull Requestには、下記のようにユーザーが機能開発のためにOpenしたものと、DependabotがOpenしたものが混在することになります。
よって下記のような処理をCI/CDで実装する必要があります。
- DependabotがOpenしたPull Requestの一覧を取得する
- 上記が1個以上あればNon-Zero Exit Codeを出力する
1.については、GitHub CLIを次のように使用すれば取得できます。
$ gh pr list --author app/dependabot Showing 1 of 1 pull request in cm-rwakatsuki/aws-cdk-app that matches your search #1 Bump moment from 2.24.0 to 2.29.2 dependabot/npm_and_yarn/moment-2.29.2
取得結果のPull Request数のカウントは、jsonオプションとjqを使えばできます。
# jsonオプションを指定すればJson形式で出力される $ gh pr list --author app/dependabot --json title [ { "title": "Bump moment from 2.24.0 to 2.29.2" } ] # Json形式の出力に対して、jqを使ったカウントを行う $ dependabot_pr_length=$(gh pr list -l dependencies --json title | jq '. | length') $ echo $dependabot_pr_length 1
CI/CD Workflow(GitHub Actions)の作成
次のようなWorkflow Config fileを作成します。今回はGitHub Actionsのものです。
on: push jobs: dependabot_alert_check: runs-on: ubuntu-latest steps: - name: Count Unclosed Pull Request id: id_count_unclosed_pr env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} run: | unclosed_pr_length=$(gh pr list --repo $GITHUB_REPOSITORY --author app/dependabot --json title | jq '. | length') echo "::set-output name=unclosed_pr_length::$unclosed_pr_length" - name: Fail Workflow Run if: ${{ steps.id_count_unclosed_pr.outputs.unclosed_pr_length != 0 }} run: exit 1 # some_ci_cd_job:
- 最初のStepでは、Dependabot security updatesの未CloseのPull Request数を取得してOutputしています。
- 次のStepでは、前StepのOutputが
0
以外なら、Non-Zero Exit Codeを出力してWorkflowをFailさせるようにしています。
動作確認
Dependabot security updatesのPull Requestが1つ以上未Closeの場合。
Non-Zero Exit Codeが出力され、Workflow実行をFailさせられました。
Dependabot security updatesのPull Requestが1つもOpen中でない場合。
Workflow実行はSuccessしました!
ハマった箇所
DependabotがOpenしたPull Requestのみを取得する方法
DependabotがOpenしたPull Requestのauthor.dependabot
は、CLIで確認するとdependabot
となっています。
$ gh pr list --json title,author [ { "author": { "login": "cm-rwakatsuki" }, "title": "機能hoge追加" }, { "author": { "login": "dependabot" }, "title": "Bump moment from 2.24.0 to 2.29.2" } ]
ユーザー(cm-rwakatsuki
)がOpenしたPull Requestのみを取得したいなら、次のようにAuthorオプションを使用します。
$ gh pr list --author "cm-rwakatsuki" Showing 1 of 1 pull request in cm-rwakatsuki/aws-cdk-app that matches your search #6 機能hoge追加 feature/hoge1
同じ要領で、DependabotがOpenしたPull Requestのみを取得できそうですが、Authorオプションにdependabot
と指定したも取得できませんでした。
$ gh pr list --author dependabot No pull requests match your search in cm-rwakatsuki/aws-cdk-app
結論としては、app/dependabot
と指定すれば取得できました。
$ gh pr list --author app/dependabot Showing 1 of 1 pull request in cm-rwakatsuki/aws-cdk-app that matches your search #1 Bump moment from 2.24.0 to 2.29.2 dependabot/npm_and_yarn/moment-2.29.2
結構ハマりましたが、Pull Requestの画面でDependabotのアカウントにマウスフォーカスすると`https://github.com/**app/dependabot**`となっていたため、気づくことが出来ました。
GitHub Actions上でのGitHub CLI実行ではRepositoryを明示的に指定する必要がある
ローカルRepository内で実行した時はえらーとならなかったgh pr list
コマンドをGitHub Actions上で実行すると、次のようなエラーとなりました。
fatal: not a git repository (or any of the parent directories): .git /usr/bin/git: exit status 128 Error: Process completed with exit code 1.
これはRunner環境がRepositoryではない(.git
が無い)ためです。よって、gh pr list --repo $GITHUB_REPOSITORY
のようにRepo
オプションで対象Repositoryを明示的に指定する必要がありました。
GraphQL APIを直接叩けばPull Requestで判断する必要が無くなりそう
もしDependabot version updates(非セキュリティのアップデート)も有効であれば、Dependabot security updatesがOpenしたPull Requestとの区別が付かないため、双方を有効にしている場合後者のみ今回のFailの対象にしたいなら何らかの工夫が必要です。GitHub CLIでDependabotのAPIが叩ければよいのですが、それが可能なサブコマンドは無さそうでした。
ただ調べてみるとGraphQL APIであればDependabotのAPIを叩くことが出来そうでした。場合によってはこちらの利用を検討すると良さそうです。
追記:下記試してみました。
参考
- [GitHub] Dependabot alerts/Dependabot security updatesを使ってみる | DevelopersIO
- Scripting Dependabot PR Merges :: Michael Vigor - JavasScript and Elixir developer
- GitHub Actionsのset-outputに複数行の標準出力を代入する場合は改行コードをエスケープしてあげる必要がある - Qiita
以上